import os, json, re, random, base64
from hashlib import md5
from json.decoder import JSONDecodeError
from datetime import datetime
from PIL import Image, ImageDraw, ImageFont
from urllib.parse import unquote

from django.conf import settings


# 配置商品图片的地址
def goods_avatar_path(instance, filename):
    return os.path.join("goods/", filename)


# 活动标签图片存放地址
def activity_tag_path(instance, filename):
    return os.path.join("activity_tag/", filename)


# 图片验证码存放地址
def verify_code_picture_path(instance, filename):
    return os.path.join("activity_tag/", filename)


# 存放用户头像地址
def user_avatar_path(instance, filename):
    return os.path.join("user/", filename)


# 生成4位随机数字
def random_verify_code() -> str:
    result = ""
    for i in range(4):
        result += str(random.randint(0, 9))

    return result


# 判断是否为正确的md5格式
def is_md5(character):
    pattern = r"^[a-zA-Z0-9]{32}$"
    res = re.match(pattern, character)
    return True if res else False


# 验证是否为手机号
def is_phone(phone):
    pattern = r"^1[35678]\d{9}$"
    res = re.match(pattern, phone)
    return True if res else False


# 验证请求参数是否合法
def valid_request_param(request) -> bool:
    _q = request.data.get("_q", request.query_params.get("_q"))
    _s = request.data.get("_s", request.query_params.get("_s"))
    # 首先请求的参数必须有_q,_s参数
    if not _q or not _s:
        return False
    # _q必须为json格式的字典，哪怕是一个空字典也行
    _q = unquote(_q)
    try:
        result = json.loads(_q)
    except JSONDecodeError:
        return False
    # 校验_q必须为一个字典类型
    if not isinstance(result, dict):
        print("_q:", result, "必须为dict类型")
        return False
    # _s是值是由_q,user-agent,path加密得来
    user_agent = request.META.get("HTTP_USER_AGENT", "")
    path = request.path or ""
    if not valid_request_data(_q, _s, user_agent, path):
        return False
    return True


# 校验_s是否加密计算一致
def valid_request_data(_q, _s, user_agent, path) -> bool:
    res = md5(bytes(user_agent + settings.REQUEST_ENCRYPT_SALT + _q + path, encoding="utf-8")).hexdigest()
    return res == _s


# 获取timedelta对象，用于比较时间相差多少
def get_timer(time):
    return datetime.now() - time


# 最后一次密码加密，与数据库做匹配
def finally_encrypt_password(password):
    salt = settings.PASSWORD_ENCRYPT_SALT
    return md5(bytes(password + salt, encoding="utf-8")).hexdigest()


# base64加密
def base64_encode(account):
    return str(base64.b64encode(bytes(account, encoding="utf-8")), encoding="utf-8")


# base64解密
def base64_decode(base64_str):
    return str(base64.b64decode(base64_str), encoding="utf-8")


# 生成token数据
def get_token(cookie_arg1):
    return md5(bytes(settings.TOKEN_SALT + cookie_arg1, encoding="utf-8")).hexdigest()


# 随机颜色RGB
def get_random_color():
    return random.randint(120, 200), random.randint(120, 200), random.randint(120, 200)


# 随机字符
def get_random_code():
    codes = [[chr(i) for i in range(48, 58)], [chr(i) for i in range(65, 91)], [chr(i) for i in range(97, 123)]]
    codes = codes[random.randint(0, 2)]
    return codes[random.randint(0, len(codes) - 1)]


# 生成验证码图片方法
def generate_captcha(code, width=140, height=60):
    # 生成验证码
    img = Image.new("RGB", (width, height), (250, 250, 250))
    draw = ImageDraw.Draw(img)
    font = ImageFont.truetype("static/font/font.ttf", size=36)
    for i in range(len(code)):
        c = code[i]
        rand_len = random.randint(-5, 5)
        draw.text((width * 0.2 * (i + 1) + rand_len, height * 0.2 + rand_len), c, font=font, fill=get_random_color())
    # 加入干扰线
    for i in range(3):
        x1 = random.randint(0, width)
        y1 = random.randint(0, height)
        x2 = random.randint(0, width)
        y2 = random.randint(0, height)
        draw.line((x1, y1, x2, y2), fill=get_random_color())
    # 加入干扰点
    for i in range(16):
        draw.point((random.randint(0, width), random.randint(0, height)), fill=get_random_color())
    # 保存图片
    filename = md5(bytes(code + "salt", encoding="utf-8")).hexdigest()
    img.save("media/captcha/" + filename + ".jpg")
    return "media/captcha/" + filename + ".jpg"
